/*
 * Copyright (c) United Binary LLC.  All rights reserved.
 * 
 * This code is licensed under the MIT License
 * 
 * SEE: http://harnessit.codeplex.com/license
 * 
 */
using System;
using System.Collections;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;

using UnitedBinary.Core.Windows.Forms;

namespace UnitedBinary.HarnessIt
{
	internal class HarnessItTraceListener : TraceListener
	{
		private ArrayList testAssociations = new ArrayList();
		private AssociatedTestTracing currentAssociation = null;
		private object locker = new object();
		private string activeTest = "None";
		private string lastActiveTest = "None";
		private RichTextComposition rtComp = new RichTextComposition();

		internal HarnessItTraceListener(RichTextBox outputRichTextBox)
		{
			if (outputRichTextBox == null)
			{
				throw new ArgumentNullException("outputRichtTextBox", "outputRichtTextBox cannot be null.");
			}

			rtComp.RichTextBox = outputRichTextBox;
			rtComp.OwnsRichTextBox = true;
			rtComp.Font = outputRichTextBox.Font;
		}

		internal string ActiveTest
		{
			get
			{
				lock(locker)
				{
					return activeTest;
				}
			}
			set
			{
				lock(locker)
				{
					activeTest = value;
				}
			}
		}

		internal void Write(string s, bool isTestOutput)
		{
			lock(locker)
			{
				if (isTestOutput == true && ActiveTest != lastActiveTest)
				{
					lastActiveTest = ActiveTest;
					rtComp.AddLine(new RichTextString("Current Test: " + ActiveTest, Color.DarkGray, rtComp.Font));

					if (ActiveTest.Trim().Length > 0)
					{
						currentAssociation = new AssociatedTestTracing(ActiveTest);
						testAssociations.Add(currentAssociation);					
					}
				}

				if (currentAssociation != null)
				{
					currentAssociation.AddTrace(s.Trim(new char [] {'\n', ' '}));
				}
				
				rtComp.Add(new RichTextString(s, Color.Black, rtComp.Font));
				RenderOnCorrectThread();
				
			}
		}

		private void RenderOnCorrectThread()
		{
			if ( rtComp.RichTextBox.InvokeRequired )
			{
				rtComp.RichTextBox.BeginInvoke( new EventHandler(
					delegate { lock(locker) rtComp.Render(); } ) );
			}
			else
			{
				lock ( locker )
				{
					rtComp.Render();
				}
			}
		}

		internal void WriteComment(string s)
		{
			lock(locker)
			{
				rtComp.AddLine(new RichTextString(s, Color.DarkGray, rtComp.Font));
				RenderOnCorrectThread();
			}
		}

		internal void WriteLine(string s, bool isTestOutput)
		{
			Write(s + "\n", isTestOutput);
		}

		public override void Write(string s)
		{
			Write(s, true);
		}

		public override void WriteLine(string s)
		{
			lock(locker)
			{
				WriteLine(s, true);
			}
		}

		internal void Clear()
		{
			lock(locker)
			{
				rtComp.Clear();
				RenderOnCorrectThread();

				testAssociations.Clear();
				
				ClearTestMemory();
			}
		}

		internal void ClearTestMemory()
		{
			lock(locker)
			{
				lastActiveTest	= "None";
				activeTest		= "None";
			}
		}

		internal RichTextComposition RichTextComp
		{
			get
			{
				return rtComp;
			}
		}

		internal AssociatedTestTracing GetAssociationByName(string name)
		{
			foreach (AssociatedTestTracing att in testAssociations)
			{
				if (att.TestName == name)
				{
					return att;
				}
			}

			return null;
		}

	}
}
